package com.dh.convert.node;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.dh.convert.exception.ConvertValueException;
import com.dh.convert.mapping.BeanMappingObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;

public class MapNode extends AbstractNode {

	public Object genObject(JsonNode jn, Object targetObject, Object currentObject,Map<String, Object> context)
			throws InstantiationException, IllegalAccessException {
		Map<String, Object> o = null;
		if (_isRoot){
			o = (Map<String, Object>) targetObject;
		}else if(currentObject !=null){
			o =  (Map<String, Object>) currentObject;
		}else{
			o = Maps.newHashMap();
		}
		return getObject(jn, targetObject, o, context);
	}

	protected Object getObject(JsonNode jn, Object targetObject, Map<String, Object> o, Map<String, Object> context)
			throws InstantiationException, IllegalAccessException {
		for (Entry<TreeNode, BeanMappingObject> e : mappingChildNodes.entrySet()) {
			TreeNode currentNode = e.getKey();
			BeanMappingObject bmo = e.getValue();
			Object  value = null;
			//BeanMappingObject不为空时，该节点需要转换生成目标值
			if(bmo != null){
				value =  currentNode.getTargetValue(jn, bmo, targetObject, context, null);
				if(value != null)
				o.put(currentNode.getNodeName(),value);
			}
			if (currentNode.isContext()) {
				if (currentNode.isNestIng())
					currentNode.genObject(jn, targetObject,value, context);
				else
					throw new ConvertValueException("context must be nesting");
			} else {
				if (currentNode.isNestIng()) {
					Object chlidObject = o.get(currentNode.getNodeName());
					if (chlidObject == null){
						o.put(currentNode.getNodeName(), currentNode.genObject(jn, targetObject, value ,context));
					}else{
						currentNode.genObject(jn, targetObject, chlidObject ,context);
					}
				} 
			}
		}
		return o;
	}
	
	@Override
	public TreeNode bulid(Field f) {
		super.bulid(f);
		this.currentClass = HashMap.class;
		this._isMap = Boolean.TRUE;
		return this;
	}

	public TreeNode bulidRootNode(Class<?> cls) {
		this.rootClass = cls;
		this._isRoot = Boolean.TRUE;
		this._isMap = Boolean.TRUE;
		this.typeName = cls.getSimpleName();
		return this;
	}

	public void bulidMappingNode(String path, BeanMappingObject bmo) {
		setChlidNode(path, bmo);
	}

	@Override
	public TreeNode getNode(String path) {
		return null;
	}

}
